package com.bdth.controller;

import com.bdth.model.*;
import com.bdth.service.IAlarmConfigService;
import com.bdth.service.IDepartmentService;
import com.bdth.service.IDeviceService;
import com.bdth.service.IRealDataService;
import com.bdth.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author: 徐斌
 * @Date: 2018-03-20 15:52
 */
@Controller
@RequestMapping("/realData")
public class RealDataController extends BaseController {

	protected static final Logger logger = LoggerFactory.getLogger(RealDataController.class);

	//将用户前台选择的车辆的Id，保存在session的key
	private static String REGISTER_KEY = "registerDeviceIds";

	private static String REGISTER_SIMNO_KEY = "registerSimNos";
	/**
	 * session 主键，存放此主键的map
	 */
	private static String UPDATE_KEY = "session_update_realdata";

	private static String REGISTER_DEVICES_KEY = "registerDevices";

	private Boolean update = false;

	@Autowired
	private IDeviceService deviceService;

	@Autowired
	private IDepartmentService departmentService;

	@Autowired
	private IAlarmConfigService alarmConfigService;

	@Autowired
	private IRealDataService realDataService;

	// 用户选择要监控的车辆，将vehicleId, simNo等存放在session中，便于定时查询实时数据(批量方法)
	@RequestMapping("/registerDevicesBatch")
	public void registerDevicesBatch(String registerDeviceIds, HttpServletRequest request, HttpServletResponse response) throws Exception {
		Map<String, Object> result = new HashMap<String, Object>();
		getDeviceIdList(request).clear();
		getDeviceList(request).clear();
		getSimNoList(request).clear();
		if (!StringUtil.isEmptyWithNullStr(registerDeviceIds)) {
			String[] deviceIds = registerDeviceIds.split(",");
			List<Integer> strDeviceIds = new ArrayList<Integer>();
			//String strVehicleIds = null;
			int count = 0;
			for (String strDeviceId : deviceIds) {
				getDeviceIdList(request).add(Integer.parseInt(strDeviceId));
				strDeviceIds.add(Integer.parseInt(strDeviceId));
			}

			List<Device> vds = deviceService.queryDeviceByIds(strDeviceIds);
			getDeviceList(request).addAll(vds);
			for (Device vd : vds) {
				getSimNoList(request).add("realData_" + vd.getSimNo());
				//vdList.Add(vd);
				count++;
			}

		}

		result.put(SUCCESS, true);
		HtmlUtil.writerJson(response, result);

	}


	/**
	 * 刷新实时数据，前端不断的采用定时刷新的方式获取实时数据，刷新实时数据表格。
	 * 如果和以前的数据没有变化，则直接不刷新，只刷新GPS数据发生变化的数据
	 * 第一次刷新update为false, 随后变为true
	 *
	 * @return
	 */
	@RequestMapping("/refreshRealData")
	public void refreshRealData(HttpServletRequest request, HttpServletResponse response) {
		Hashtable outputData = new Hashtable();
		HashMap params = new HashMap();
		//是否是更新模式，更新模式下，没有变化的数据不更新到前台，节省流量
		this.update = "true".equals("" + request.getParameter("update"));
		String devId = request.getParameter("dvcId");
		if (StringUtil.isEmptyWithNullStr(devId)) {
			try {
				if (getDeviceIdList(request).size() > 0) {
					List<Map> result = this.getRealDataListBatch(request);

					//按照车牌号排序
					Collections.sort(result, new Comparator<Map>() {
						public int compare(Map o1, Map o2) {
							if (o1.get("simNo") == null)
								return -1;
							String simNo1 = "" + o1.get("simNo");
							String simNo2 = "" + o2.get("simNo");
							return simNo1.compareTo(simNo2);
						}

					});

					outputData.put("rows", result);
				}
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}

			HtmlUtil.writerJson(response, outputData);
		} else {
			// 单车监控，用于生成监控车辆轨迹
			params.put("devId", Integer.parseInt(devId));
			try {
				List result = deviceService.queryDevice(params);
				if (result != null && result.size() > 0) {
					Map resultMap = (Map) result.get(0);
					String simNo = "" + resultMap.get("simNo");
					String depName = "" + resultMap.get("depName");
					String equipName = "" + resultMap.get("equipName");
					String communicationModel = "" + resultMap.get("communicationModel");
					String typeName = "" + resultMap.get("typeName");
					GPSRealData rd = realDataService.get("realData_" + simNo);
					Map resultMap1 = new HashMap();
					//resultMap1.put("vehicleId", rd.getCarId());
					resultMap1.put("simNo", simNo);
					resultMap1.put("depName", depName);
					resultMap1.put("equipName", equipName);
					resultMap1.put("communicationModel", communicationModel);
					resultMap1.put("typeName", typeName);
					if (rd != null) {
						// 将实时数据更新到map
						setRealDataMap(resultMap1, rd);
					}
					this.convert(resultMap1);
					Map<String, Object> context = new HashMap<String, Object>();
					context.put(SUCCESS, true);
					context.put("data", resultMap1);
					HtmlUtil.writerJson(response, context);
				}
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}
		}


	}

	private List<Integer> getDeviceIdList(HttpServletRequest request) {
		List<Integer> vehicleIdList = (List<Integer>) request.getSession(true).getAttribute(REGISTER_KEY);
		if (vehicleIdList == null) {
			vehicleIdList = new ArrayList<Integer>();
			request.getSession(true).setAttribute(REGISTER_KEY, vehicleIdList);
		}
		return vehicleIdList;
	}

	private List<String> getSimNoList(HttpServletRequest request) {
		List<String> simNoList = (List<String>) request.getSession(true).getAttribute(REGISTER_SIMNO_KEY);
		if (simNoList == null) {
			simNoList = new ArrayList<String>();
			request.getSession(true).setAttribute(REGISTER_SIMNO_KEY, simNoList);
		}
		return simNoList;
	}


	private List<Device> getDeviceList(HttpServletRequest request) {
		List<Device> vds = (List<Device>) request.getSession(true).getAttribute(REGISTER_DEVICES_KEY);
		if (vds == null) {
			vds = new ArrayList<Device>();
			request.getSession(true).setAttribute(REGISTER_DEVICES_KEY, vds);
		}
		return vds;
	}


	private Map<String, Date> getUpdateMap(HttpServletRequest request) {
		Map<String, Date> updateMap = (Map<String, Date>) request.getSession(true).getAttribute(
				UPDATE_KEY);
		if (updateMap == null) {
			updateMap = new HashMap<String, Date>();
			request.getSession(true).setAttribute(UPDATE_KEY, updateMap);
		}
		return updateMap;
	}

	private List<Map> getRealDataListBatch(HttpServletRequest request) throws Exception {
		List<Map> result = new ArrayList<Map>();
		Hashtable depAllMap = new Hashtable();
		List<String> simNoList = this.getSimNoList(request);
		List<Integer> vehicleIdList = this.getDeviceIdList(request);
		Map<String, GPSRealData> realDataMap = new HashMap<String, GPSRealData>();
		//调用gps服务器提供的实时数据服务，获取实时数据
		List<GPSRealData> realList = realDataService.getRealDataList(simNoList);
		for (GPSRealData rd : realList) {
			realDataMap.put(rd.getSimNo(), rd);
		}

		Map<String, Date> updateMap = this.getUpdateMap(request);
		if (update == false) {
			updateMap.clear();// 第一次加载要清空表格
		}
		List<Device> vds = this.getDeviceList(request);
		Map<String, Object> map = new HashMap<String, Object>();
		List<Department> allDepList = departmentService.queryByMapList(map);
		for (Department department : allDepList) {
			depAllMap.put(department.getId(), department);
		}
		for (Device vd : vds) {
			Map<String, Comparable> rowData = new HashMap();
			Department dep = (Department) depAllMap.get(vd.getDepId());
			rowData.put("dvcId", vd.getId());
			rowData.put("depName", dep.getDepName());
			rowData.put("simNo", vd.getSimNo());
			rowData.put("equipName", vd.getEquipName());
			rowData.put("communicationModel", vd.getCommunicationModel());
			rowData.put("typeName", vd.getTypeName());
			if (realDataMap.containsKey(vd.getSimNo())) {
				GPSRealData rd = realDataMap.get(vd.getSimNo());
				if (rd != null) {
					setRealDataMap(rowData, rd);
				}
			}


			if (rowData.containsKey("sendTime")) {
				Date sendTime = DateUtil.getDateFromString("" + rowData.get("sendTime"));
				if (update && updateMap.containsKey(vd.getSimNo())) {
					Date lastSendTime = updateMap.get(vd.getSimNo());
					if (lastSendTime.compareTo(sendTime) == 0) {
						continue;// 说明数据没有发生变化,不刷新
					}
				}
				updateMap.put(vd.getSimNo(), sendTime);
			} else if (update) {
				continue;
			}

			try {
				// 对返回的每行数据，进行格式化转换
				convert(rowData);
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}
			result.add(rowData);
		}
		return result;
	}


	// 用户取消勾选要监控的分组
	@RequestMapping("/registerDepUncheck")
	public void registerDepUncheck(HttpServletRequest request, HttpServletResponse response, String depIdStr) throws Exception {
		List<Hashtable> result = new ArrayList<Hashtable>();
		String depStr = depIdStr.substring(3, depIdStr.length());
		int depIdInt = 0;
		if (depStr != null) {
			depIdInt = Integer.parseInt(depStr);
		}
		List<Integer> depIds = getDepIds(depIdInt);

		List<Device> deviceList = deviceService.queryByDepIds(depIds);

		for (Device vd : deviceList) {
			Hashtable rowData = new Hashtable();
			rowData.put("devId", vd.getId());
			rowData.put("simNo", vd.getSimNo());
			result.add(rowData);
			getDeviceIdList(request).remove((Integer) vd.getId());
		}

		getDeviceList(request).clear();
		getSimNoList(request).clear();
		List<Device> vds = deviceService.queryDeviceByIds(getDeviceIdList(request));
		getDeviceList(request).addAll(vds);
		for (Device vd : vds) {
			getSimNoList(request).add("realData_" + vd.getSimNo());
		}

		Hashtable outputData = new Hashtable();
		try {

			outputData.put("rows", result);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
		HtmlUtil.writerJson(response, outputData);
	}


	// 用户取消勾选要监控的设备
	@RequestMapping("/registerDevicesUncheck")
	public void registerDevicesUncheck(HttpServletRequest request, HttpServletResponse response, String deviceIdStr) throws Exception {
		List<Hashtable> result = new ArrayList<Hashtable>();
		String deviceStr = deviceIdStr.substring(1, deviceIdStr.length());
		int deviceIdInt = 0;
		if (deviceStr != null) {
			deviceIdInt = Integer.parseInt(deviceStr);
		}
		Device device = deviceService.queryById(deviceIdInt);

		if (device != null) {
			getDeviceIdList(request).remove((Integer) device.getId());
		}

		getDeviceList(request).clear();
		getSimNoList(request).clear();
		List<Device> vds = deviceService.queryDeviceByIds(getDeviceIdList(request));
		getDeviceList(request).addAll(vds);
		for (Device vd : vds) {
			getSimNoList(request).add("realData_" + vd.getSimNo());
		}

		Hashtable outputData = new Hashtable();
		try {
			outputData.put("rows", result);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
		HtmlUtil.writerJson(response, outputData);
	}


	private void setRealDataMap(Map rowData, GPSRealData rd) {
		//rowData.put("valid", rd.getValid());
		rowData.put("latitude", rd.getLatitude());
		rowData.put("longitude", rd.getLongitude());
		//rowData.put("altitude", rd.getAltitude());
		rowData.put("alarmState", rd.getAlarmState());
		rowData.put("status", rd.getStatus());
		//rowData.put("oil", rd.getOil());
		//rowData.put("signal", rd.getSignal());
		rowData.put("location", rd.getLocation());
		rowData.put("mileage", rd.getMileage());
		rowData.put("online", rd.getOnline());
		rowData.put("sendTime", rd.getSendTime());
		rowData.put("velocity", rd.getVelocity());
		//rowData.put("recordVelocity", rd.getRecordVelocity());
		rowData.put("direction", rd.getDirection());
		//rowData.put("enclosureAlarm", rd.getEnclosureAlarm());
		//rowData.put("enclosureType", rd.getEnclosureType());
		rowData.put("enclosureId", rd.getEnclosureId());
		//rowData.put("overSpeedAreaId", rd.getOverSpeedAreaId());
		//rowData.put("overSpeedAreaType", rd.getOverSpeedAreaType());
		//rowData.put("routeAlarmType", rd.getRouteAlarmType());
		//rowData.put("routeSegmentId", rd.getRouteSegmentId());
		//rowData.put("runTimeOnRoute", rd.getRunTimeOnRoute());

	}


	private void convert(Map rowData) {
		//显示车辆ACC开关等状态
		String displaySignalState = "door";

		// String vehicleType = "" + rowData["vehicleType");
		//this.convert(rowData, "vehicleType", "VehicleType");

		// String plateColor = "" + rowData["plateColor");
		//this.convert(rowData, "plateColor", "plateColor");
		if (rowData.containsKey("sendTime") && rowData.get("sendTime") != null) {
		/*	if (Constants.STATE_TYPE_BARKER.equals(displaySignalState)) {
				//显示刹车、转向
				int signal = (int) rowData.get("signal");
				signal = 24;
				String descr = this.getSignalDescr(signal);
				rowData.put("status", descr);
			} else {*/
			//显示车辆ACC开关等状态
			String status = "" + rowData.get("status");
			String descr = getStatusDescr(status);
			rowData.put("status", descr);
			//}

			String alarmState = "" + rowData.get("alarmState");
			alarmState = this.getAlarmDescr(alarmState);

	/*		if (rowData.get("valid") != null) {
				boolean valid = (Boolean) rowData.get("valid");
				rowData.put("valid", valid ? "有效" : "无效");
			}*/


			Date sendTime = DateUtil.getDateFromString("" + rowData.get("sendTime"));
			rowData.put("sendTime",
					DateUtil.getFomartDate(sendTime, "yyyy-MM-dd HH:mm:ss"));

			Double latitude = Double.parseDouble("" + rowData.get("latitude"));
			Double longitude = Double
					.parseDouble("" + rowData.get("longitude"));

			// 坐标加偏
			PointLatLng pl = MapFixService.fix(latitude, longitude,
					Constants.MAP_GOOGLE);
			rowData.put("latitude", pl.getLat());
			rowData.put("longitude", pl.getLng());

			rowData.put("orgLatitude", latitude);
			rowData.put("orgLongitude", longitude);

			int direction = (Integer) rowData.get("direction");
			String directionDescr = this.getDirectionDescr(direction);
			rowData.put("directionDescr", directionDescr);

			String enclosureType = "" + rowData.get("enclosureType");
			int enclosureId = (Integer) rowData.get("enclosureId");
		/*	if (enclosureType > 0) {
				int enclosureAlarm = (Integer) rowData.get("enclosureAlarm");
				String temp = enclosureAlarm == 0 ? "进入" : "离开";
				alarmState += this.getAreaTypeDescr(enclosureType) + "Id:"
						+ enclosureId + temp + "报警,";
			}*/

			if (StringUtil.isEmptyWithNullStr(alarmState))
				alarmState = "无";
			rowData.put("alarmStateDescr", alarmState);// 报警状态描述
		}
		if (rowData.get("location") == null) {
			rowData.put("location", "");
		}


	}


	/**
	 * 0：无特定位置； 1：圆形区域； 2：矩形区域； 3：多边形区域； 4：路段
	 *
	 * @param areaType
	 * @return
	 */
	protected String getAreaTypeDescr(int areaType) {
		if (areaType == 0)
			return "无特定位置";
		else if (areaType == 1)
			return "圆形区域";
		else if (areaType == 2)
			return "矩形区域";
		else if (areaType == 3)
			return "多边形区域";
		else if (areaType == 4)
			return "路段";
		return "未知区域类型";
	}

	protected String getDirectionDescr(int direction) {
		String descr = "";
		if (direction == 0) {
			descr = "正北";
		} else if (direction == 90) {
			descr = "正东";
		} else if (direction == 180) {
			descr = "正南";
		} else if (direction == 270) {
			descr = "正西";
		} else if (direction == 45) {
			descr = "东北";
		} else if (direction == 135) {
			descr = "东南";
		} else if (direction == 225) {
			descr = "西南";
		} else if (direction == 315) {
			descr = "西北";
		} else if (direction < 90) {
			descr = "东偏北" + (90 - direction) + "度";
		} else if (direction > 90 && direction < 180) {
			descr = "东偏南" + (direction - 90) + "度";
		} else if (direction > 180 && direction < 270) {
			descr = "西偏南" + (270 - direction) + "度";
		} else if (direction > 270 && direction < 360) {
			descr = "西偏北" + (direction - 270) + "度";
		}
		return descr;
	}

	protected String getStatusDescr(String status) {
		StringBuilder sb = new StringBuilder();

		if (StringUtil.isEmptyWithNullStr(status) == false) {
			char[] ch = status.toCharArray();
			if (ch.length == 32) {
				int m = 31;
				int c = ch[m - 0] - 48;
				sb.append(c == 1 ? "ACC开" : "ACC关").append(",");
				c = ch[m - 1] - 48;
				sb.append(c == 1 ? "定位" : "未定位").append(",");
				c = ch[m - 4] - 48;
				sb.append(c == 1 ? "停运" : "运营").append(",");
				c = ch[m - 10] - 48;
				sb.append(c == 1 ? "油路断开" : "油路正常").append(",");
				c = ch[m - 11] - 48;
				sb.append(c == 1 ? "电路断开" : "电路正常").append(",");
				c = ch[m - 12] - 48;
				sb.append(c == 1 ? "车门加锁" : "车门解锁").append(",");
			}
		}

		return sb.toString();
	}

	private static String[] signalDescr = new String[]{"近光灯", "远光灯", "右转向灯",
			"左转向灯", "制动", "倒档"};

	protected String getSignalDescr(int signal) {
		StringBuilder sb = new StringBuilder();
		String strStatus = Integer.toBinaryString(signal);
		strStatus = StringUtil.leftPad(strStatus, 32, '0');

		char[] ch = strStatus.toCharArray();
		for (int m = 0; m < ch.length && m < signalDescr.length; m++) {
			int c = ch[31 - m] - 48;
			if (StringUtil.isEmptyWithNullStr(signalDescr[m]) == false) {
				sb.append(signalDescr[m]).append(c == 1 ? "开" : "关").append(",");
			}
		}

		return sb.toString();
	}

	/**
	 * 报警描述
	 *
	 * @param alarm
	 * @return
	 */
	protected String getAlarmDescr(String alarm) {
		StringBuilder sb = new StringBuilder();

		if (StringUtil.isEmptyWithNullStr(alarm) == false) {
			char[] ch = alarm.toCharArray();
			for (int m = 0; m < ch.length; m++) {
				int tag = Integer.parseInt("" + ch[m]);
				if (tag == 1) {
					int alarmId = 31 - m; // 倒序，转换为部标的报警序号
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("alarmType", "" + alarmId);
					List<AlarmConfig> bd = alarmConfigService.queryByAlarmType(map);
					if (bd != null && bd.size() > 0) {
						sb.append(bd.get(0).getName()).append(",");
					}
				}
			}
		}

		return sb.toString();
	}

}
